package core

import (
	"bufio"
	"fmt"
	errors2 "github.com/pkg/errors"
	"hpmGo/utils"
	"os"
	"strings"
)

type RcParser struct {
	configMap map[string]string
	keys      []string
	path      string
}

func (rc *RcParser) ToJson() {
	for _, key := range rc.keys {
		fmt.Printf("%s = %s\n", key, rc.configMap[key])
	}
}

func (rc *RcParser) Get(key string) string {
	return rc.configMap[key]
}

func (rc *RcParser) Set(key, value string) {
	rc.configMap[key] = value
	rc.keys = rc.keys[0:0]
	for val := range rc.configMap {
		rc.keys = append(rc.keys, val)
	}
}

func (rc *RcParser) Delete(key string) {
	delete(rc.configMap, key)
	rc.keys = utils.Filter(rc.keys, func(index int, item string) bool {
		return item == key
	})
}

func (rc *RcParser) SaveToFile() error {
	f, _ := os.OpenFile(rc.path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC|os.O_APPEND, os.ModePerm)
	for key := range rc.configMap {
		err := os.Setenv(key, rc.configMap[key])
		line := fmt.Sprintf("%s = %s", key, rc.configMap[key])
		_, err = fmt.Fprintln(f, line)
		if err != nil {
			return errors2.WithMessage(err, "SaveToFile: Fprintln failed")
		}
	}
	return nil
}

func (rc *RcParser) SetMap(config map[string]string) error {
	for key := range config {
		err := os.Setenv(key, config[key])
		if err != nil {
			return errors2.WithMessage(err, "SetMap: Setenv failed")
		}
		rc.keys = append(rc.keys, key)
	}
	rc.configMap = config
	return nil
}

func (rc *RcParser) Parse() error {
	f, err := os.OpenFile(rc.path, os.O_RDONLY, os.ModePerm)
	if err != nil {
		return errors2.WithMessage(err, "Parse: OpenFile failed")
	}
	scanner := bufio.NewScanner(f)
	scanner.Split(bufio.ScanLines)
	for scanner.Scan() {
		lineArr := strings.Split(scanner.Text(), "=")
		key := strings.TrimSpace(lineArr[0])
		value := strings.TrimSpace(lineArr[1])
		rc.keys = append(rc.keys, key)
		rc.configMap[key] = value
	}
	return nil
}

func FromPath(path string) (rc RcParser, err error) {
	rc = RcParser{path: path, configMap: map[string]string{}}
	err = rc.Parse()
	return
}

func FromMap(config map[string]string, path string) (rc RcParser, err error) {
	rc = RcParser{path: path, configMap: map[string]string{}}
	err = rc.SetMap(config)
	return
}

func SaveMapToFile(config map[string]string, path string) (rc RcParser, err error) {
	rc, err = FromMap(config, path)
	err = rc.SaveToFile()
	return
}
